#ifndef DEVICEHANDLER_H_INCLUDED
#define DEVICEHANDLER_H_INCLUDED

#include <ctype.h>
#include <linux/types.h>
#include <linux/virtio_ring.h>
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <termios.h>
#include <unistd.h>

#include "Devices.h"

struct termios orig_term;

void *_check_pointer(unsigned long addr, unsigned int size,  unsigned int line);

//Macro para el manejo de las funciones de chequeo de punteros
#define check_pointer(addr,size) _check_pointer(addr, size, __LINE__)

//Obtiene el siguiente descriptor de una cola
unsigned next_desc(struct vring_desc *desc, unsigned int i, unsigned int max);

//Realiza la ejecución de la interrupción en la cola de dispositivos
void trigger_irq(struct virtqueue *vq);

/*
 * Se empaca la primera posción del buffer disponible como un elemento iovec
 * Espera si es necesario y retorna el descriptor obtenido.
 */
unsigned wait_for_vq_desc(struct virtqueue *vq,struct iovec iov[], unsigned int *out_num, unsigned int *in_num);

//Se le indica al guest que  un buffer fue utilizado
void add_used(struct virtqueue *vq, unsigned int head, int len);

/* Añade un buffer y genera una interrupción */
void add_used_and_trigger(struct virtqueue *vq, unsigned head, int len);

// Consola para el manejo de la salida del programa
struct console_abort {
	int count;
	struct timeval start;
};

//Maneja la obención del input desde la consola
void console_input(struct virtqueue *vq);

//Output a la consola
void console_output(struct virtqueue *vq);

//Ciclo que realiza la atención a un thread de manera ciclicaS
int do_thread(void *_vq);

//Mata el proceso y restaura la consola
void kill_launcher(int signal);

//Hace un reset a un dispositivo
void reset_device(struct device *dev);

//Crea un thread que atiende la cola de dispositivos virtuales
void create_thread(struct virtqueue *vq);

// Obtiene el estado de una de las caracterisiticas del dispositivo
bool accepted_feature(struct device *dev, unsigned int bit);

//Incializa el dispositivo
void start_device(struct device *dev);

//Limpia los dispositivos del sistema
void cleanup_devices(void);

/* Manejo de la actualización del estado de los dispositivos*/
void update_device_status(struct device *dev);

// Notifica los cambios del estado de los dispositivos durante el arranque del sistema
void handle_output(unsigned long addr);
#endif
